
#pragma once

#include <entt/entt.hpp>
#include "ly/manager.hpp"
#include "ly/path.hpp"
#include "ly/polygon.hpp"
#include "ly/properties.hpp"

namespace ly {

class Cell;

class LY_API Shapes {
 public:
  typedef entt::registry reg_t;
  typedef std::shared_ptr<Shapes> shapes_sptr;
  typedef std::weak_ptr<Shapes> shapes_wptr;
  typedef std::shared_ptr<Cell> cell_sptr;
  typedef std::weak_ptr<Cell> cell_wptr;

 public:
  Shapes() {};
  Shapes(cell_wptr parent_cell) : mp_cell(parent_cell) {};
  ~Shapes() {};

  template <typename... Args>
  static shapes_sptr create(Args&&... args) {
    return std::make_shared<Shapes>(std::forward<Args>(args)...);
  }

  reg_t& reg() { return m_reg; }
  cell_sptr cell() { return mp_cell.lock(); };
  void cell(cell_sptr c) { mp_cell = c; };

  entt::entity create_entity() { return m_reg.create(); };

  void emplace_or_replace(entt::entity e, const Polygon& com);
  void emplace_or_replace(entt::entity e, const Path& com);
  void emplace_or_replace(entt::entity e, const ObjectWithProperties& com);

  void undo(Op* op);
  void redo(Op* op);

  void print_all();

 private:
  template <typename T>
  void emplace(entt::entity e, const T& comp);

 private:
  reg_t m_reg;
  cell_wptr mp_cell;
};
}  // namespace ly
